package com.baofu.paycore.biz.engine.generator.impl;

import com.baofu.account.service.facade.enums.FreezeTypeEnum;
import com.baofu.paycore.biz.engine.command.Command;
import com.baofu.paycore.biz.engine.command.impl.BalanceCommand;
import com.baofu.paycore.biz.engine.command.impl.PreAuthUnFreezeTransferCommand;
import com.baofu.paycore.biz.engine.generator.CommandGenerator;
import com.baofu.paycore.common.enums.FundTypeEnum;
import com.baofu.paycore.service.facade.enums.PayCoreErrorCode;
import com.baofu.paycore.manager.model.preAuth.PreAuthBO;
import com.baofu.paycore.manager.model.preAuth.SubPreAuthBO;
import com.baofu.paycore.service.facade.enums.AuthConfirmModeEnum;
import com.baofu.paycore.service.facade.enums.PayToolTypeEnum;
import com.baofu.paycore.service.facade.enums.RequestSystemEnum;
import com.google.common.collect.Lists;
import com.system.commons.exception.BizServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * 预授权完成指令生成
 * <p>
 * <p>
 * 1、生成命令
 * </p>
 * User: xin deng  Date: 16/9/1 ProjectName: paycore Version: 1.0
 */
@Slf4j
@Service
public class AuthConfirmCommandGenerator implements CommandGenerator<PreAuthBO> {

    /**
     * 生成指令
     *
     * @param payBaseBO 订单模型
     * @return 命令列表
     */
    @Override
    public List<Command> generatorCommands(PreAuthBO payBaseBO) {
        List<Command> list = Lists.newArrayList();

        List<SubPreAuthBO> subPreAuthBOs = payBaseBO.getSubPreAuthBO();

        subPreAuthBOs.forEach(subPreAuthBO -> {
            PayToolTypeEnum payToolTypeEnum = PayToolTypeEnum.explain(subPreAuthBO.getPayToolType());
            switch (payToolTypeEnum) {
                case ACCOUNT:
                    if (FundTypeEnum.PRE_AUTH_CONFIRM_FEE.getCode().equals(subPreAuthBO.getFundType())) {
                        list.add(getBalanceCommand(payBaseBO, subPreAuthBO));
                        break;
                    }
                    list.add(assemblePreAuthConfirm(payBaseBO, subPreAuthBO));
                    break;
                case BANK_CARD:
                    log.error("预授权暂不支持 银行卡:{}", payBaseBO.getPayNo());
                    throw new BizServiceException(PayCoreErrorCode.VALUE_NOT_SUPPORT, "暂不支持银行卡预授权撤销功能");
            }
        });
        return list;
    }

    /**
     * 组装预授权解冻指令
     *
     * @param preAuthBO 预授权参数
     */
    private PreAuthUnFreezeTransferCommand assemblePreAuthConfirm(PreAuthBO preAuthBO, SubPreAuthBO subPreAuthBO) {

        PreAuthUnFreezeTransferCommand command = new PreAuthUnFreezeTransferCommand();
        command.setTransferAmt(preAuthBO.getAmt());
        command.setUnFreezeAmt(preAuthBO.getAmt());
        command.setRelationNo(preAuthBO.getRelationNo());
        command.setBizType(preAuthBO.getBizType());
        command.setSubBizType(preAuthBO.getSubBizType());
        command.setCcy(preAuthBO.getCcy());
        command.setFundDetailNo(subPreAuthBO.getFundDetailNo());
        command.setOperator(preAuthBO.getOperator());
        command.setRequestDate(new Date());
        command.setRequestNo(subPreAuthBO.getFundDetailNo());
        command.setFreezeReqNo(subPreAuthBO.getFreezeNo());
        command.setRequestSystem(RequestSystemEnum.PAYCORE.getCode());
        command.setFreezeType(FreezeTypeEnum.DRAW.getCode());
        command.setFreezeCode(subPreAuthBO.getFreezeCode());
        command.setTradeLogId(preAuthBO.getTradeLogId());
        command.setServiceCode(preAuthBO.getServiceCode());
        command.setFundingChannel(subPreAuthBO.getFundingChannel());
        command.setSubFundingChannel(subPreAuthBO.getSubFundingChannel());
        command.setPayerAccNo(subPreAuthBO.getPayerAccNo());
        command.setPayeeAccNo(subPreAuthBO.getPayeeAccNo());
        command.setSyncPayeeFlag(Boolean.TRUE);
        command.setPayNo(preAuthBO.getPayNo());

        return command;
    }

    /**
     * 封装指令
     *
     * @param preAuthBO    预授权对象
     * @param subPreAuthBO 预授权资金对象
     * @return 余额指令
     */
    public BalanceCommand getBalanceCommand(PreAuthBO preAuthBO, SubPreAuthBO subPreAuthBO) {
        BalanceCommand balanceCommand = new BalanceCommand();

        balanceCommand.setRelationNo(preAuthBO.getRelationNo());
        balanceCommand.setRequestOrderNo(preAuthBO.getPayNo());
        balanceCommand.setRequestBizNo(subPreAuthBO.getFundDetailNo());
        balanceCommand.setRequestSystem(preAuthBO.getRequestSystem());
        balanceCommand.setRequestDate(preAuthBO.getRequestDate());
        balanceCommand.setServiceCode(preAuthBO.getServiceCode());
        balanceCommand.setPayNo(preAuthBO.getPayNo());

        balanceCommand.setBizType(preAuthBO.getBizType());
        balanceCommand.setSubBizType(preAuthBO.getSubBizType());
        balanceCommand.setFundingChannel(subPreAuthBO.getFundingChannel());
        balanceCommand.setSubFundingChannel(subPreAuthBO.getSubFundingChannel());

        balanceCommand.setPayeeAccNo(subPreAuthBO.getPayeeAccNo());
        balanceCommand.setPayerAccNo(subPreAuthBO.getPayerAccNo());
        balanceCommand.setCcy(subPreAuthBO.getCcy());
        balanceCommand.setAmount(subPreAuthBO.getAmt());
        balanceCommand.setBizChargeAmt(subPreAuthBO.getAmt());

        balanceCommand.setAsyPayeeFlag(Boolean.TRUE);
        balanceCommand.setFundDetailNo(subPreAuthBO.getFundDetailNo());

        balanceCommand.setEventNo(subPreAuthBO.getEventNo());
        balanceCommand.setOperator(preAuthBO.getOperator());
        balanceCommand.setRemark(preAuthBO.getDescription());
        balanceCommand.setTraceLogId(preAuthBO.getTradeLogId());

        return balanceCommand;
    }
}
